/*
 * dsmGestorEntrega.cpp
 *
 *  Created on: Dec 15, 2013
 *      Author: m
 */

#include "DSMComun.h"
#include "SharedMemory2.h"
#include "MessageQueue.h"
#include "Semaphore.h"
#include "ColaRemotaTransmisorDirecto.h"
#include "ColaRemotaReceptorDirecto.h"
#include "CPrinter.h"
#include "StringUtils.h"

using ipc::CPrinter;
using ipc::MessageQueue;
using ipc::SharedMemory2;
using ipc::Semaphore;

int main ( int argc, char* argv[] )
{
    std::string nombreColaRemotaPedidos;
    std::string dsmIdString;
    int dsmId;
    int *contadorPedidos;

    CPrinter::setHeader( "dsmGestorEntrega" );

    if ( argc != 2 )
    {
        CPrinter::printErr( "Cantidad de argumentos invalidos" );
        exit( 1 );
    }

    dsmIdString = argv[1];
    dsmId = StringUtils::StringToNumber<int>( dsmIdString );

    CPrinter::setHeader( "dsmGestorEntrega", dsmId );

    CPrinter::printOut( "INICIADO" );

    nombreColaRemotaPedidos = COLA_PEDIDO_BROKER_BASENAME + dsmIdString;

    MessageQueue<TokenDSM> colaEntregaToken =
            MessageQueue<TokenDSM>::get( DSM_IPC_BASEFILE, COLA_ENTREGA_TOKEN );
    MessageQueue<TokenDSM> colaLiberarToken =
            MessageQueue<TokenDSM>::get( DSM_IPC_BASEFILE, COLA_LIBERAR_TOKEN );

    Semaphore mutexContadorPedidos =
                Semaphore::get( DSM_IPC_BASEFILE, MTX_CONT_PEDIDOS );
    contadorPedidos =
            SharedMemory2<int>::get( DSM_IPC_BASEFILE, SHM_CONT_PEDIDOS );
    MessageQueue<PedidoDSM> colaPedidoBroker =
            MessageQueue<PedidoDSM>::get( DSM_IPC_BASEFILE, COLA_PEDIDO_TOKEN );

    ColaRemotaTransmisorDirecto transmisor;
    ColaRemotaReceptorDirecto receptor( COLA_LIBERAR_BROKER_BASENAME + dsmIdString );

    while ( true )
    {
        TokenDSM token;
        int pedidosAProcesar;

        // Espero el token desde el Gestor de tokens
//           CPrinter::printOut( "Recibiendo el token del gestor");
        token = colaEntregaToken.get( dsmId );

//        CPrinter::printOut( "Recibi el token del gestor");

        // Leo la cantidad de pedidos actual
        mutexContadorPedidos.p( dsmId - 1 );
        pedidosAProcesar = contadorPedidos[ dsmId - 1 ];
        mutexContadorPedidos.v( dsmId - 1 );

//            CPrinter::printOut( "Voy a procesar %d pedidos", pedidosAProcesar );

        // uno a uno voy entregando el token a cada agente y espero que me lo devuelva
        while ( pedidosAProcesar > 0 )
        {
            PedidoDSM pedido;

            pedido = colaPedidoBroker.get( dsmId );

            CPrinter::printOut( "Entregando el token a: %s", pedido.colaRespuesta );
            transmisor.enviarMensaje<TokenDSM>( pedido.colaRespuesta, token );
            CPrinter::printOut( "Esperando que el agente devuelva el token" );
            token = receptor.recibirMensaje<TokenDSM>();
            CPrinter::printOut( "Agente %s devolvio el Token", pedido.colaRespuesta );

            pedidosAProcesar--;

            mutexContadorPedidos.p( dsmId - 1 );
            contadorPedidos[dsmId - 1] -= 1;
            mutexContadorPedidos.v( dsmId - 1 );
        }

        // Devuelvo el token al Gestor de tokens
//        CPrinter::printOut( "Termine de procesar pedidos, devuelvo el token al GestorToken" );
        colaLiberarToken.put( dsmId, token );
    }

    return 0;
}
